package com.atguigu.gmall.cart.service;

import com.alibaba.fastjson.JSON;
import com.atguigu.gmall.cart.feign.GmallPmsClient;
import com.atguigu.gmall.cart.feign.GmallSmsClient;
import com.atguigu.gmall.cart.feign.GmallWmsClient;
import com.atguigu.gmall.cart.interceptors.LoginInterceptor;
import com.atguigu.gmall.cart.mapper.CartMapper;
import com.atguigu.gmall.cart.pojo.Cart;
import com.atguigu.gmall.common.bean.UserInfo;
import com.atguigu.gmall.common.bean.ResponseVo;
import com.atguigu.gmall.common.exception.CartException;
import com.atguigu.gmall.pms.entity.SkuAttrValueEntity;
import com.atguigu.gmall.pms.entity.SkuEntity;
import com.atguigu.gmall.sms.vo.ItemSaleVo;
import com.atguigu.gmall.wms.entity.WareSkuEntity;
import net.bytebuddy.asm.Advice;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.BoundHashOperations;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.math.BigDecimal;
import java.util.List;
import java.util.stream.Collectors;

/**
 * Created by IntelliJ IDEA.
 *
 * @Author: 86182
 * @Date: 2021/8/20
 * @Time: 16:09
 * @Version:
 */
@Service
public class CartService {
    private static final String KEY_PREFIX = "cart:info:";
    private static final String PRICE_PREFIX = "cart:price:";
    @Autowired
    private StringRedisTemplate redisTemplate;
    @Autowired
    private AsyncCartService asyncCartService;

    @Autowired
    private GmallPmsClient pmsClient;
    @Autowired
    private GmallWmsClient wmsClient;
    @Autowired
    private GmallSmsClient smsClient;
    @Autowired
    private CartMapper cartMapper;

    public void addCart(Cart cart) {
        //获取登录状态: userInfo
        String userId = this.getUserId();
        // 组装外层的key
        String key = KEY_PREFIX + userId;
        // 获取当前用户内层购物车map
        BoundHashOperations<String, Object, Object> hashOps = this.redisTemplate.boundHashOps(key);
        //判断当前用户是否包含该商品
        String skuId = cart.getSkuId().toString(); //要新增的skuId
        BigDecimal count = cart.getCount(); //要新增的数量
        if (hashOps.hasKey(skuId)) {
            // 如果包含,更新数量(累加)
            String json = hashOps.get(skuId).toString();
            cart = JSON.parseObject(json, Cart.class);
            cart.setCount(cart.getCount().add(count)); //购物车中已有数量 累加新增的数量
            // 使用新的cart 覆盖掉 旧的cart
            // 同时更新mysql 同步 后续再去改成异步
            //this.cartMapper.update(cart, new UpdateWrapper<Cart>().eq("user_id", userId).eq("sku_id", skuId));
            this.asyncCartService.update(userId,cart,skuId);
        } else {
            //如果不包含,新增一条记录
            cart.setUserId(userId);
            cart.setCheck(true);
            //查询sku相关的信息
            ResponseVo<SkuEntity> skuEntityResponseVo = this.pmsClient.querySkuById(cart.getSkuId());
            SkuEntity skuEntity = skuEntityResponseVo.getData();
            if (skuEntity == null) {
                throw new CartException("要添加的商品不存在");
            }
            cart.setTitle(skuEntity.getTitle());
            cart.setPrice(skuEntity.getPrice());
            cart.setDefaultImage(skuEntity.getDefaultImage());

            //查询库存
            ResponseVo<List<WareSkuEntity>> wareResponseVo = this.wmsClient.queryWareSkuBySkuId(skuEntity.getId());
            List<WareSkuEntity> wareSkuEntities = wareResponseVo.getData();
            if (!CollectionUtils.isEmpty(wareSkuEntities)) {
                cart.setStore(wareSkuEntities.stream().anyMatch(wareSkuEntity -> wareSkuEntity.getStock() - wareSkuEntity.getStockLocked() > 0));
            }

            //销售属性
            ResponseVo<List<SkuAttrValueEntity>> skuAttrsResponseVo = this.pmsClient.querySaleAttrValueBySkuId(skuEntity.getId());
            List<SkuAttrValueEntity> skuAttrValueEntities = skuAttrsResponseVo.getData();
            if (!CollectionUtils.isEmpty(skuAttrValueEntities)) {
                cart.setSaleAttrs(JSON.toJSONString(skuAttrValueEntities));
            }

            //营销信息
            ResponseVo<List<ItemSaleVo>> listResponseVo = this.smsClient.querySalesBySkuId(skuEntity.getId());
            List<ItemSaleVo> itemSaleVos = listResponseVo.getData();
            if (!CollectionUtils.isEmpty(itemSaleVos)) {
                cart.setSales(JSON.toJSONString(itemSaleVos));
            }

            //新增到数据库
            //this.cartMapper.insert(cart);
            this.asyncCartService.insert(userId,cart);
            //向 redis 中添加 实时价格 缓存
            this.redisTemplate.opsForValue().set(PRICE_PREFIX + skuId, skuEntity.getPrice().toString());
        }
        hashOps.put(skuId, JSON.toJSONString(cart));

    }

    private String getUserId() {
        //从拦截器中获取userInfo
        UserInfo userInfo = LoginInterceptor.getUserInfo();
        //获取userKey
        String userId = userInfo.getUserKey();
        //如果登录了(userId不为空), 用userId覆盖掉userKey
        if (userInfo.getUserId() != null) {
            userId = userInfo.getUserId().toString();
        }
        return userId;
    }

    /**
     * 新增成功后的回显查询
     *
     * @param skuId
     * @return
     */
    public Cart queryCartBySkuId(Long skuId) {
        // 获取登录用户信息
        String userId = this.getUserId();

        // 获取当前用户的购物车操作对象
        BoundHashOperations<String, Object, Object> hashOps = this.redisTemplate.boundHashOps(KEY_PREFIX + userId);
        String json = hashOps.get(skuId.toString()).toString();
        if (StringUtils.isBlank(json)) {
            throw new CartException("对应的购物车记录不存在");
        }
        return JSON.parseObject(json, Cart.class);
    }

    public List<Cart> queryCarts() {
        UserInfo userInfo = LoginInterceptor.getUserInfo();
        //1.查询未登录的购物车,相当于拿到内存的map<skuId,cartJson>
        BoundHashOperations<String, Object, Object> unLoginHashOps = this.redisTemplate.boundHashOps(KEY_PREFIX + userInfo.getUserKey());
        // 获取未登录用户的购物车json字符串集合
        List<Object> cartJsons = unLoginHashOps.values();
        //如果未登录的购物车集合不为空,转化为购物车集合
        List<Cart> unLoginCarts = null;
        if (!CollectionUtils.isEmpty(cartJsons)) {
            //未登录的购物车集合
            unLoginCarts = cartJsons.stream().map(cartJson -> {
                Cart cart = JSON.parseObject(cartJson.toString(), Cart.class);
                cart.setCurrentPrice(new BigDecimal(redisTemplate.opsForValue().get(PRICE_PREFIX + cart.getSkuId())));
                return cart;
            }).collect(Collectors.toList());
        }
        //2.获取登录信息,判断是否登陆(userId = null说明没有登陆) , 没有登录则直接返回未登录的购物车即可
        Long userId = userInfo.getUserId();
        if (userId == null) {
            return unLoginCarts;
        }
        //3.如果登陆了 , 需要合并未登录的购物车到已登陆的购物车中
        BoundHashOperations<String, Object, Object> loginHashOps = this.redisTemplate.boundHashOps(KEY_PREFIX + userId);
        // 判断未登录的购物车是否为空,不为空则需要遍历未登录的购物车,然后合并到已登陆的购物车中
        if (!CollectionUtils.isEmpty(unLoginCarts)) {
            unLoginCarts.forEach(cart -> {
                // 参照新增购物车: 如果已登录购物车包含了该商品 则更新数量  如果没有包含该商品,则新增一条记录
                String skuId = cart.getSkuId().toString();
                BigDecimal count = cart.getCount();
                if (loginHashOps.hasKey(skuId)) {
                    String cartJson = loginHashOps.get(skuId).toString();
                    cart = JSON.parseObject(cartJson, Cart.class);
                    cart.setCount(cart.getCount().add(count));
                    // 更新到数据库
                    this.asyncCartService.update( userId.toString(),cart, skuId);
                } else {
                    // 用userId 把userKey 给替换掉
                    cart.setUserId(userId.toString());
                    this.asyncCartService.insert(userId.toString(),cart);
                }
                loginHashOps.put(skuId, JSON.toJSONString(cart));
            });
            //4.删除未登陆的购物车
            this.redisTemplate.delete(KEY_PREFIX + userInfo.getUserKey());
            this.asyncCartService.deleteCartByUserId(userInfo.getUserKey());
        }

        //5.查询已登录的购物车
        List<Object> loginCartJsons = loginHashOps.values();
        if (CollectionUtils.isEmpty(loginCartJsons)) {
            return null;
        }
        return loginCartJsons.stream().map(cartJson -> {
            Cart cart = JSON.parseObject(cartJson.toString(), Cart.class);
            cart.setCurrentPrice(new BigDecimal(redisTemplate.opsForValue().get(PRICE_PREFIX + cart.getSkuId())));
            return cart;
        }).collect(Collectors.toList());
    }

    public void updateNum(Cart cart) {
        // 获取登录状态
        String userId = this.getUserId();
        // 根据登录信息查询当前用户的购物车
        BoundHashOperations<String, Object, Object> hashOps = this.redisTemplate.boundHashOps(KEY_PREFIX + userId);
        if (!hashOps.hasKey(cart.getSkuId().toString())) {
            throw new CartException("当前用户没有该条购物车记录");
        }

        // 获取当前用户对应的购物车记录
        String cartJson = hashOps.get(cart.getSkuId().toString()).toString();
        BigDecimal count = cart.getCount();
        cart = JSON.parseObject(cartJson, Cart.class);
        cart.setCount(count);

        hashOps.put(cart.getSkuId().toString(), JSON.toJSONString(cart));
        this.asyncCartService.update(userId,cart , cart.getSkuId().toString());
    }

    public void deleteCart(Long skuId) {
        String userId = this.getUserId();
        BoundHashOperations<String, Object, Object> hashOps = this.redisTemplate.boundHashOps(KEY_PREFIX + userId);
        hashOps.delete(skuId.toString());
        this.asyncCartService.deleteCartByUserIdAndSkuId(userId, skuId);
    }

    public List<Cart> queryCheckedCarts(Long userId) {
        String key = KEY_PREFIX + userId;
        BoundHashOperations<String, Object, Object> hashOps = this.redisTemplate.boundHashOps(key);
        List<Object> cartJsons = hashOps.values();
        if (CollectionUtils.isEmpty(cartJsons)){
            return null;
        }
        return cartJsons.stream().map(cartJson->JSON.parseObject(cartJson.toString(),Cart.class)).filter(cart->cart.getCheck()).collect(Collectors.toList());
    }
}














